/** @file gui_editbox.h
    @brief An editbox widget */

#ifndef G3_GUI_EDITBOX_H
#define G3_GUI_EDITBOX_H

#include <algorithm>
#include <string>
#include "gui/gui_label.h"

#include "../timer.h"

namespace G3 {
namespace GUI {

/** The delay before key repetition kicks in */
extern long DelayBeforeKeyRepetitionKicksIn;
/** When the key repetition is on, this is the delay between two inserted characters */
extern long KeyRepeatDelay;
/** The timer that measures the delay between two inserted characters */
extern TIMER KeyDelayTimer;

/** @class EDITBOX
    @brief An editbox class */
class EDITBOX: public WIDGET {
    friend class GUI;

	public:
        /**
            @brief A constructor
        */
		EDITBOX ();

        /**
            @brief An empty destructor
        */
		virtual ~EDITBOX () {
		}

        /** Typing caret position */
		long CaretPos;
		/** Width of the text line */
		long TextWidth;
		/** Width of the caret */
		byte CaretWidth;

        /** Background colors for different editbox states */
		COL4F BgColor [3];
		/** Foreground colors for different editbox states */
		COL4F FgColor [3];
		/** Caret colors for different editbox states */
		COL4F CaretColor [3];

		/** What was the last key that was pressed ? */
		int LastKey;
		/** What were the last key's modifiers ? */
		short LastModifier;
		/** Are we repeating that key ? */
		bool RepeatingAKey;

        /**
            @brief Assignment operator
            @param[in] aEditBox Reference to the editbox to be copied
            @return Reference to the freshly copied editbox
        */
		EDITBOX& operator= (const EDITBOX &aEditBox);

        /** The callback type of a keypress signal */
		typedef boost::signal3<void, INPUT *, SDL_keysym *, float> SIG_KEY_EVENT;
		/** The callback type of a content change signal */
		typedef boost::signal1<void, EDITBOX *> SIG_CHANGE;
        /** A function pointer type for the content change callback */
		typedef void (*CHANGE_HANDLER)(EDITBOX *);

        /**
            @brief Sets the value-change event callback
            @param[in] aChangeHandler Pointer to the callback function
            @return The produced signal connection
        */
		SIG_CONNECTION doOnValueChange (CHANGE_HANDLER aChangeHandler);
        /**
            @brief Sets the enter-pressed event callback
            @param[in] aChangeHandler Pointer to the callback function
            @return The produced signal connection
        */
		SIG_CONNECTION doOnEnterPressed (CHANGE_HANDLER aChangeHandler);

        /**
            @brief Creates the editbox
            @param[in] aRect Reference to the editbox rectangle
            @param[in] aFont Pointer to the caption font
        */
		void Create (const RECTI &aRect, FONT *aFont);

        /**
            @brief Shows editbox foreground
        */
		void ShowForeground () { FgVisible = true; }
		/**
            @brief Shows editbox background
		*/
		void ShowBackground () { BgVisible = true; }
		/**
            @brief Shows editbox caret
		*/
		void ShowCaret () { CaretVisible = true; }
        /**
            @brief Hides editbox foreground
        */
		void HideForeground () { FgVisible = false; }
		/**
            @brief Hides editbox background
		*/
		void HideBackground () { BgVisible = false; }
		/**
            @brief Hides editbox caret
		*/
		void HideCaret () { CaretVisible = false; }

        /**
            @brief Sets editbox dimensions
            @param[in] aRect Reference to the new rectangle
        */
		void SetRect (const RECTI &aRect);

        /**
            @brief Shrinks the editbox to its contents
        */
		void Shrink ();

        /**
            @brief Attaches a font to the text
            @param[in] aFont pointer to the new font
        */
		void AttachFont (G3::FONT *aFont);

        /**
            @brief Sets editbox value
            @param[in] aValue Reference to the new value string
        */
		void SetValue (const string &aValue);

        /**
            @brief Processes character input
            @param[in] c Input character
            @param[in] m Modifier flags
        */
		void ProcCharInput (int c, short m);

        /**
            @brief Gets the value of the editbox
            @return The value string
        */
		string GetValue ();

        /**
            @brief Draws the editbox
            @param[in] aElapsedTime The elapsed time since the last call
        */
		void Draw (float aElapsedTime = 0.0f);

        /**
            @brief Gets the type of this widget
            @return The type index \see TYPE_MANAGER
        */
		virtual uint GetType () { return MainTypeMgr.GetType ("W_EDITBOX"); }

        /**
            @brief Is this widget static ?
            @return False.
        */
		virtual bool IsStatic () { return false; }

    private:
		/** Is the foreground part of the editbox visible ? */
		bool FgVisible;
		/** Is the background part of the editbox visible ? */
		bool BgVisible;
		/** Is the caret visible ? */
		bool CaretVisible;

        /** Key-down signal */
		SIG_KEY_EVENT SigKeyDown;
		/** Key-up signal */
		SIG_KEY_EVENT SigKeyUp;
		/** Value-change signal */
		SIG_CHANGE SigValueChanged;
		/** Enter-pressed signal */
		SIG_CHANGE SigEnterPressed;

        /** Signal connections for value-change events */
		vector<SIG_CONNECTION> ConnValueChanged;
		/** Signal connections for enter-pressed events */
		vector<SIG_CONNECTION> ConnEnterPressed;
};

}
}

#endif // G3_GUI_EDITBOX_H
